#include "mainwindow.h"
#include"message/save.h"
#include "qdir.h"
#include "register.h"
#include"httpmgr.h"
#include"message/chatframe.h"
#include "ui_mainwindow.h"

#include<QWindow>
#include <QScrollBar>

/*QListWidget::Item{background-color: rgb(240, 240, 240);}
QListWidget::Item:hover{background-color: rgb(240, 240, 240); }
QListWidget::item:selected{
    background-color: rgb(240, 240, 240);
    color:black;
    border: 1px solid  rgb(240, 240, 240);
}
QListWidget::item:selected:!active{border: 1px solid  rgb(240, 240, 240); background-color: rgb(240, 240, 240); color:rgb(51,51,51); } */

MainWindow::MainWindow(const QString& myname, QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->label_2->setText(myname);
    // 禁用横向滚动条
    ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //垂直滚动模式为逐像素滚动
    ui->listWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
    ui->photograph->setPixmap("./data/head portrait/" + myname + "_HeadPortrait.jpg");

    connect(HttpMgr::GetInstance().get(), &HttpMgr::sig_find_mod_finish, this, &MainWindow::Find_user);

    //连接数据库 如果没有就创建
    Save::Instance(ui->label_2->text());
    QStringList d = Save::Instance().getTables();
    for (QString name : d){
        if (name == "sqlite_sequence"){
            continue;
        }
        establish(name);
    }

    //与讯飞星火建立连接
    xunfei = new QNetworkAccessManager(this);
    connect(xunfei, &QNetworkAccessManager::finished, this, &MainWindow::xunfeiDispose);
    xunfeinet.setUrl(QUrl("https://spark-api-open.xf-yun.com/v1/chat/completions"));
    xunfeinet.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    xunfeinet.setRawHeader("Authorization","Bearer ee5240895053f3173d2cea06d4da9e2e:MTM3OTUyNjVjMWNiOTE5ZGVlMDczZDQ5");

    connectTCP();//连接tcp服务器 用于消息发送与接收

    // 用于传输发送的消息
    QJsonObject messageObject;
    messageObject["role"] = "user";
    messageObject["content"] = "";
    QJsonArray messagesArray;
    messagesArray.append(messageObject);
    userObject["model"] = "4.0Ultra";
    userObject["messages"] = messagesArray;
}

MainWindow::~MainWindow()
{
    xunfei->deleteLater();
    socket->deleteLater();
    delete ui;
}

void MainWindow::resizeEvent(QResizeEvent *)
{
    ui->listWidget->setFixedWidth(this->width() - 222);
    ui->listWidget->update();

    // 更新所有项的大小
    for (int i = 0; i < ui->listWidget->count(); ++i) {
        QListWidgetItem *item = ui->listWidget->item(i);
        QSize size(item->sizeHint());
        size.setWidth(this->width() - 240);
        item->setSizeHint(size); // 示例大小
    }
}

//发送数据
void MainWindow::on_pushButton_clicked()
{
    QString s = ui->textEdit->toPlainText();
    if (s.isEmpty()){
        return;
    }
    ui->textEdit->clear();

    //判断发送到哪里
    if (ui->label->text() == "与讯飞星火的聊天"){
        addChatFrame(ui->label->text(), s, UserType::Current_User);
        xunfeixinghuo(s);
        return;
    }
    send(s);

    message.sender = ui->label_2->text();
    message.text = s;
    message.type = 1;
    Save::Instance().Add(ui->label->text(), message);
    addChatFrame(ui->label->text(), s, UserType::Current_User);
}

//查找用户
void MainWindow::on_pushButton_4_clicked()
{
    HttpMgr::GetInstance()->PostHttpReq(QUrl("http://116.198.241.238:8080/inquire"), QByteArray(ui->lineEdit->text().toUtf8()), ReqID::ID_Find_USER, Modules::Find_USER);
}

void MainWindow::on_lineEdit_returnPressed()
{
    HttpMgr::GetInstance()->PostHttpReq(QUrl("http://116.198.241.238:8080/inquire"), QByteArray(ui->lineEdit->text().toUtf8()), ReqID::ID_Find_USER, Modules::Find_USER);
}

//向服务器查找一个用户
void MainWindow::Find_user(QByteArray imageData, ReqID, ErrorCodes err)
{
    qDebug("查找");

    if (err != ErrorCodes::StatusOK){
        QMessageBox::warning(this, "警告", "用户不存在");
        return;
    }

    QDir dir("./data/head portrait");
    // 使用 QDir::entryList 查找文件
    QStringList fileList = dir.entryList(QStringList() << (ui->lineEdit->text() + "_HeadPortrait.jpg"), QDir::Files);
    if (fileList.isEmpty()) {
        QFile file("./data/head portrait/" + ui->lineEdit->text() +  "_HeadPortrait.jpg");
        if (file.open(QIODevice::WriteOnly))
        {
            file.write(imageData);
            file.close();
        }
    }

    establish(ui->lineEdit->text());
}

//与讯飞星火的聊天
void MainWindow::on_pushButton_2_clicked()
{
    ui->listWidget->clear();
    ui->label->setText("与讯飞星火的聊天");
}
void MainWindow::xunfeixinghuo(const QString &s) {
    // 修改消息内容
    QJsonArray messagesArray = userObject.value("messages").toArray();
    if (!messagesArray.isEmpty()) {
        QJsonObject messageObject = messagesArray[0].toObject();
        messageObject["content"] = s;
        messagesArray[0] = messageObject;
        userObject["messages"] = messagesArray;
    }
    QJsonDocument jsonDocument(userObject);
    QByteArray jsonData = jsonDocument.toJson();//二进制字节数组

    xunfei->post(xunfeinet, jsonData);
}
void MainWindow::xunfeiDispose(QNetworkReply* reply){
    QString all = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(all.toUtf8());
    QJsonObject rootObj = doc.object();
    QJsonObject r =  rootObj.value("choices").toArray()[0].toObject().value("message").toObject();

    addChatFrame("与讯飞星火的聊天", r.value("content").toString(), UserType::Other_Users);
    reply->deleteLater();
}

//添加一行消息
void MainWindow::addChatFrame(const QString &linkman, const QString &text, const UserType &type, const NewsType &nt, bool b)
{
    //如果项的父指针是QListWidget 就无法指定位置插入
    QListWidgetItem *item = new QListWidgetItem();
    ChatFrame *f = nullptr;
    switch (type){
    case UserType::Current_User:
        f = new ChatFrame(ui->label_2->text(), text, type, nt, ui->listWidget);
        break;
    case UserType::Other_Users:
        f = new ChatFrame(linkman, text, type, nt, ui->listWidget);
        break;
    }

    connect(f, &ChatFrame::InterfaceUpdate, this, [item](const QSize& size){
        item->setSizeHint(size);
    });

    item->setSizeHint(f->sizeHint());
    if (b){//为true代表是读取 将数据放入顶部
        // 插入新项到列表的顶部
        ui->listWidget->insertItem(0, item);
    }
    else{
        ui->listWidget->addItem(item);
    }
    ui->listWidget->setItemWidget(item, f);
}

//添加新页面
void MainWindow::establish(const QString &name){
    if (address_book.contains(name)){
        return;
    }
    Save::Instance().createForm(name);

    QPushButton *button = new QPushButton(name, ui->widget_3);
    connect(button, &QPushButton::clicked, this, [button, this]{
        button->setStyleSheet("color: rgb(0, 0, 0);");
        if (button->text() == ui->label->text()){
            return;
        }
        ui->label->setText(button->text());
        ui->listWidget->clear();
        row = Save::Instance().getSun(button->text());
        toLoad();
        ui->listWidget->scrollToBottom();
    });
    ui->verticalLayout_3->insertWidget(2, button);
    address_book[button->text()] = button;
}

void MainWindow::toLoad()
{
    for (int i = 0; i < 12; i++){
        if (row == 0){
            return;
        }

        Save::Instance().ReadALine(row--, ui->label->text(), message);
        if (message.sender == ui->label_2->text()){
            addChatFrame(ui->label->text(), message.text, UserType::Current_User, static_cast<NewsType>(message.type), true);
             continue;
        }
        addChatFrame(ui->label->text(), message.text, UserType::Other_Users, static_cast<NewsType>(message.type), true);
    }
    if (row == 0){
        return;
    }
    QListWidgetItem *item = new QListWidgetItem();
    QPushButton *button = new QPushButton("显示更多");

    connect(button, &QPushButton::clicked, this, [item, this]{
        // int nowRow = row;
        ui->listWidget->takeItem(0);
        delete item;
        toLoad();
    });

    button->setFixedSize(QSize(120, 20));
    item->setSizeHint(button->sizeHint());
    // 插入新项到列表的顶部
    ui->listWidget->insertItem(0, item);
    ui->listWidget->setItemWidget(item, button);
}

//退出登录
void MainWindow::on_pushButton_3_clicked()
{
    logOut();
    Register *r = new Register;
    r->show();
    this->close();//法通常用于关闭对象的一些资源，比如窗口、文件等
    this->deleteLater();//通常用于删除对象
}

void MainWindow::connectTCP()
{
    //与服务器建立tcp连接 用于通信
    socket = new QTcpSocket(this);
    connect(socket, &QTcpSocket::readyRead, this, &MainWindow::onDataReceived);//接收到数据时触发
    connect(socket, &QTcpSocket::connected, this, [this]{
        //连接成功后发送认证信息
        QJsonObject userObject;
        userObject["authCode"] = "zhangjunjieiizhangbaofan";
        userObject["state"] = 0;//0表示连接
        userObject["sender"] = ui->label_2->text();
        userObject["data"];
        QJsonDocument jsonDocument(userObject);
        QByteArray jsonData = jsonDocument.toJson();

        socket->write(jsonData);
    });//连接成功时触发
    // 假设已经连接到后端服务器
    socket->connectToHost("116.198.241.238", 8081);
     // socket->connectToHost("127.0.0.1", 8081);
}

void MainWindow::logOut()
{
    QJsonObject userObject;
    userObject["authCode"] = "zhangjunjieiizhangbaofan";
    userObject["state"] = -1;//-1退出
    userObject["sender"] = ui->label_2->text();
    QJsonDocument jsonDocument(userObject);
    QByteArray jsonData = jsonDocument.toJson();

    socket->write(jsonData);
}

void MainWindow::fileSaving(const QByteArray ba, const QString &name)
{
    QFile file("./data/other files/" + name);
    if (!file.open(QIODevice::WriteOnly)) {
        qDebug() << "打开文件写入失败:" << file.errorString();
        return;
    }
    qint64 bytesWritten = file.write(ba);
    if (bytesWritten == -1) {
        qDebug() << "写入文件失败:" << file.errorString();
        file.close();
        return;
    }

    file.close();
}

//文件
void MainWindow::on_pushButton_5_clicked()
{
    static const QString videoFormat("mp4 avi mkv wmv mov flv webm mpeg mpg vob");
    static const QString pictureFormat("jpg jpeg png bmp webp");

    QString fileName = QFileDialog::getOpenFileName(this,"选择文件");
    if (fileName.isEmpty()) {
        return;
    }
    // 使用 QFileInfo 来获取文件信息
    QFileInfo fileInfo(fileName);
    QString fileType = fileInfo.suffix(); // 获取文件扩展名
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open file for reading:" << file.errorString();
        return;
    }
    QByteArray data = file.readAll();
    file.close();

    fileSaving(data, fileInfo.fileName());

    NewsType nt;
    if (videoFormat.contains(fileType)){
        qDebug() << "视频";
        nt = NewsType::video;
    }else if (pictureFormat.contains(fileType)){
        qDebug() << "图片";
        nt = NewsType::picture;
    }else{
        qDebug() << "其他文件";
        nt = NewsType::rests;
    }

    send(data.toBase64(), nt, fileInfo.fileName());
    message.sender = ui->label_2->text();
    message.text ="./data/other files/" + fileInfo.fileName();
    message.type =static_cast<int>(nt) ;
    Save::Instance().Add(ui->label->text(), message);
    addChatFrame(ui->label->text(), message.text, UserType::Current_User, nt);
}

void MainWindow::send(const QString &data, const NewsType &n, const QString &fileName){
    QJsonObject userData;
    userData["recipient"] = ui->label->text();
    userData["information"] = data;
    userData["fileName"] = fileName;

    QJsonObject userObject;
    userObject["authCode"] = "zhangjunjieiizhangbaofan";
    userObject["state"] = static_cast<int>(n);
    userObject["sender"] = ui->label_2->text();
    userObject["data"] = userData;
    QJsonDocument jsonDocument(userObject);
    QByteArray jsonData = jsonDocument.toJson();

    socket->write(jsonData);
}

//处理接收到的数据 别人给我发送的消息
void MainWindow::onDataReceived() {
    QByteArray all= socket->readAll();
    static int ii = 0;
    qDebug() << "接收数据：" << ii++;
    // 将新数据添加到缓存中
    cache.append(all);
    //等待接收完毕
    if (all.indexOf("}}") == -1){
        return;
    }
    qDebug() << "已接收到完整json";

    // 将数据解析为QJsonDocument
    QJsonParseError jsonError;
    QJsonDocument doc = QJsonDocument::fromJson(cache, &jsonError);
    if (jsonError.error != QJsonParseError::NoError) {
        qDebug() << "Failed to parse JSON:" << jsonError.errorString();
        cache.clear();
        return;
    }
    QJsonObject rootObj = doc.object();
    QJsonObject data = rootObj.value("data").toObject();

    //获得发送者名字
    QString sender_name = rootObj.value("sender").toString();
    if (sender_name.isEmpty()){
        cache.clear();
        return;
    }
    //检查通讯录是否有, 没有就添加
    if (!address_book.contains(sender_name)){
        HttpMgr::GetInstance()->PostHttpReq(QUrl("http://116.198.241.238:8080/inquire"), QByteArray(sender_name.toUtf8()), ReqID::ID_Find_USER, Modules::Find_USER);
        establish(sender_name);
    }
    QString string = data.value("information").toString();
    address_book[sender_name]->setStyleSheet("color: rgb(255, 0, 0);");  //标记未读

    message.sender = sender_name;
    NewsType state = static_cast<NewsType>(rootObj.value("state").toInt());
    message.type = static_cast<int>(state);
    switch(state){
    case NewsType::text:
        message.text =string ;
        break;
    case NewsType::picture:
    case NewsType::video:
    case NewsType::rests:
        // 将字符串解码为QByteArray
        fileSaving(QByteArray::fromBase64(string.toUtf8()), data.value("fileName").toString());
        message.text = "./data/other files/" + data.value("fileName").toString();
        break;
    case NewsType::videoCall:
        qDebug() << sender_name;

        cache.clear();
        if (string == "同意"){
            qDebug() << sender_name +  "同意";
            vc->start_pull();
            message.text =string ;
            break;
        }
        else if (string == "拒绝"){
            qDebug() << sender_name +  "拒绝";
            message.text =string ;
            delete vc;
            break;
        }
        vc = new VideoCall(message.sender, ui->label_2->text(), this);
        vc->setWindowTitle(sender_name);

        //弹窗
        QMessageBox::StandardButton rb = QMessageBox::question(NULL, sender_name + "发起了视频通话", "你想要接听吗", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        if(rb == QMessageBox::Yes) {
            send("同意", NewsType::videoCall, "");
            vc->show();
            vc->start_pull();
        }
        else send("拒绝", NewsType::videoCall, "");
        break;
    }
    Save::Instance().Add(sender_name, message);

    //如果当前活跃的联系人 与消息不符合 那么我们只保存聊天记录 不显示
    if (ui->label->text() != sender_name){
        cache.clear();
        return;
    }
    //添加新一行数据
    addChatFrame(sender_name, message.text, UserType::Other_Users, state);
    cache.clear();
}

void MainWindow::on_pushButton_7_clicked()
{
    send("发起视频通话", NewsType::videoCall, "");


    // vc = new VideoCall(ui->label->text(), ui->label_2->text(), this);
    vc = new VideoCall(ui->label->text(), ui->label->text(), this);
    vc->setWindowTitle(ui->label->text());
    vc->show();
}
